/**
 * 创建一个初始化组件
 */
import fs from 'fs';
import inquirer from 'inquirer';
import colors from 'colors';
import { resolve } from 'path';

const cwdPath = process.cwd();

const questions = [
  {
    type: 'input',
    name: 'componentInput',
    message: '组件名称：',
  },
  {
    type: 'list',
    choices: ['element', 'collection', 'view', 'module', 'behavior', 'addon'],
    name: 'groupInput',
    message: '组件所属组：',
  },
];

/**
 * 创建文件
 * @param {string} path 文件路径
 * @param {string} data 文件内容
 * @param {string} desc 文件描述
 */
const createFile = (path, data = '') => {
  fs.writeFile(path, data, (err) => {
    if (err) {
      console.error(colors.red('错误：'), err);
    } else {
      console.info(colors.blue('文件 %s 已经创建成功！'), path);
    }
  });
};

/**
 * 首字母大写
 * @param {string} name 名称
 * @returns
 */
const ucfirst = (name) => {
  const nameLower = name.toLowerCase();
  return nameLower.at(0).toUpperCase().concat(nameLower.substring(1));
};

/**
 * 生成组件文件
 * @param {string} component 组件名
 * @param {string} group 组名
 */
const generate = (component, group) => {
  // 组件导出写入入口文件
  const indexPath = resolve(cwdPath, 'src', 'index.ts');
  const expStr = `export { default as ${ucfirst(component)} } from './${component.toLowerCase()}';`;
  let indexContent = fs.readFileSync(indexPath).toString();
  if (indexContent.match(new RegExp(expStr))) {
    console.warn(colors.yellow('\n组件 %s 已经在 /src/index.ts 中\n'), component);
    return;
  }

  try {
    fs.appendFileSync(indexPath, `${expStr}\n`);
    console.info(colors.blue('组件 %s 已写入 /src/index.ts'), component);
  } catch (error) {
    console.error(colors.red('错误：'), error);
  }

  // 创建组件文件夹
  fs.mkdirSync(resolve(cwdPath, 'src', component.toLowerCase()));

  // 写入组件文件 index.ts
  const componentIndex = [
    `import ${ucfirst(component)} from './${ucfirst(component)}';`,
    '',
    `export type { ${ucfirst(component)}Props } from './${ucfirst(component)}';`,
    `export * from './type';`,
    '',
    `export default ${ucfirst(component)};`,
    '',
  ];

  try {
    fs.writeFileSync(resolve(cwdPath, 'src', component.toLowerCase(), 'index.ts'), componentIndex.join('\n'));
    console.info(colors.blue('组件文件已写入：/src/%s/index.ts'), component.toLowerCase());
  } catch (error) {
    console.error(colors.red('错误：'), error);
  }

  // 写入组件文件 type.ts
  const componentType = [
    `import type { LegacyRef } from 'react';`,
    '',
    `export interface ${ucfirst(component)}Options {`,
    '  /**',
    '   * 转发 ref',
    '   */',
    '  forwardedRef?: LegacyRef<HTMLElement>;',
    '}',
    '',
  ];

  try {
    fs.writeFileSync(resolve(cwdPath, 'src', component.toLowerCase(), 'type.ts'), componentType.join('\n'));
    console.info(colors.blue('组件文件已写入：/src/%s/type.ts'), component.toLowerCase());
  } catch (error) {
    console.error(colors.red('错误：'), error);
  }

  // 写入组件文件 defaultProps.ts
  const componentDefaultProps = [
    `import type { ${ucfirst(component)}Options } from './type';`,
    '',
    `export const ${component.toLowerCase()}DefaultProps: ${ucfirst(component)}Options = {};`,
    '',
  ];

  try {
    fs.writeFileSync(
      resolve(cwdPath, 'src', component.toLowerCase(), 'defaultProps.ts'),
      componentDefaultProps.join('\n'),
    );
    console.info(colors.blue('组件文件已写入：/src/%s/defaultProps.ts'), component.toLowerCase());
  } catch (error) {
    console.error(colors.red('错误：'), error);
  }

  // 写入组件主体文件
  const componentMain = [
    `import { createElement, HTMLAttributes, type FC } from 'react';`,
    `import classNames from 'classnames';`,
    '',
    `import { ${component.toLowerCase()}DefaultProps } from './defaultProps';`,
    `import type { ${ucfirst(component)}Options } from './type';`,
    '',
    `export interface ${ucfirst(component)}Props extends ${ucfirst(
      component,
    )}Options, HTMLAttributes<HTMLDivElement> {}`,
    '',
    `const ${ucfirst(component)}: FC<${ucfirst(component)}Props> = (props) => {`,
    `  const { className, children, forwardedRef, ...${component.toLowerCase()}Props } = props;`,
    '',
    '  return createElement(',
    `    'div',`,
    `    { ref: forwardedRef, className: classNames('ui', '${component.toLowerCase()}', className), ...${component.toLowerCase()}Props },`,
    `    children,`,
    '  );',
    '};',
    '',
    `${ucfirst(component)}.displayName = '${ucfirst(component)}';`,
    `${ucfirst(component)}.defaultProps = ${component.toLowerCase()}DefaultProps;`,
    '',
    `export default ${ucfirst(component)};`,
    '',
  ];

  try {
    fs.writeFileSync(
      resolve(cwdPath, 'src', component.toLowerCase(), `${ucfirst(component)}.tsx`),
      componentMain.join('\n'),
    );
    console.info(colors.blue('组件文件已写入：/src/%s/%s.tsx'), component.toLowerCase(), ucfirst(component));
  } catch (error) {
    console.error(colors.red('错误：'), error);
  }

  // 创建组件示例文件夹
  fs.mkdirSync(resolve(cwdPath, 'examples', component.toLowerCase()));

  // 创建示例基本文件
  const componentDemoBase = [
    `import { ${ucfirst(component)} } from '@fomantic-react/main';`,
    '',
    `export default () => <${ucfirst(component)} />;`,
  ];

  try {
    fs.writeFileSync(resolve(cwdPath, 'examples', component.toLowerCase(), 'base.tsx'), componentDemoBase.join('\n'));
    console.info(colors.blue('组件示例文件已写入：/examples/%s/base.tsx'), component.toLowerCase());
  } catch (error) {
    console.error(colors.red('错误：'), error);
  }

  // 写入组件文档
  const componentMd = [
    '---',
    `title:  - ${ucfirst(component)}`,
    'order: ',
    'toc: content',
    'group:',
    `  title:  - ${ucfirst(group)}s`,
    '---',
    '',
    `#  - ${ucfirst(component)}`,
    '',
    `<code src="examples/${component.toLowerCase()}/base.tsx"></code>`,
    '',
  ];

  try {
    fs.writeFileSync(resolve(cwdPath, 'docs', 'components', `${component.toLowerCase()}.md`), componentMd.join('\n'));
    console.info(colors.blue('组件示例文件已写入：/docs/components/%s.md'), component.toLowerCase());
  } catch (error) {
    console.error(colors.red('错误：'), error);
  }

  console.log(colors.green('\n组件初始化成功！\n'));
};

/**
 * 初始化组件
 */
const init = () => {
  inquirer.prompt(questions).then((answers) => {
    console.log('\n');
    generate(answers.componentInput, answers.groupInput);
  });
};

init();
